package com.waikuai.shop.util;

import com.waikuai.shop.entity.User;
import com.waikuai.shop.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import java.util.List;

/**
 * 密码加密工具类
 * 用于将数据库中现有的明文密码加密为BCrypt格式
 * 
 * 使用方法：
 * 方式1（推荐）：使用Maven命令行运行
 *   mvn spring-boot:run -Dspring-boot.run.arguments=--encrypt-passwords
 * 
 * 方式2：使用java -jar运行
 *   java -jar target/employee-shop-backend.jar --encrypt-passwords
 * 
 * 方式3：在IDE中运行
 *   1. 找到Spring Boot主类的运行配置
 *   2. 在Program arguments中添加：--encrypt-passwords
 *   3. 运行应用
 * 
 * 工具会自动：
 * - 检测所有未加密的密码（不以$2a$开头）
 * - 将明文密码转换为BCrypt格式
 * - 为没有支付密码的用户设置默认支付密码（123456）
 * - 完成后自动退出应用
 * 
 * @author waikuai
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PasswordEncryptionTool implements CommandLineRunner {

    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Override
    public void run(String... args) throws Exception {
        // 检查是否需要执行密码加密
        for (String arg : args) {
            if ("--encrypt-passwords".equals(arg)) {
                log.info("开始执行密码加密任务...");
                encryptAllPasswords();
                log.info("密码加密任务完成！");
                // 加密完成后退出应用
                System.exit(0);
            }
        }
    }

    /**
     * 加密所有未加密的用户密码
     */
    public void encryptAllPasswords() {
        log.info("========================================");
        log.info("开始加密现有用户密码");
        log.info("========================================");

        // 查询所有用户
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getDeleted, 0); // 只处理未删除的用户
        List<User> users = userMapper.selectList(wrapper);

        if (users == null || users.isEmpty()) {
            log.info("没有找到需要处理的用户");
            return;
        }

        log.info("找到{}个用户，开始检查和加密密码...", users.size());

        int encryptedCount = 0;
        int skippedCount = 0;
        int paymentPasswordCount = 0;

        for (User user : users) {
            boolean updated = false;

            // 检查并加密登录密码
            if (user.getPassword() != null && !isEncrypted(user.getPassword())) {
                String originalPassword = user.getPassword();
                String encryptedPassword = passwordEncoder.encode(originalPassword);
                user.setPassword(encryptedPassword);
                updated = true;
                encryptedCount++;
                log.info("用户 [{}] (ID: {}) 的登录密码已加密", user.getUsername(), user.getId());
            } else {
                skippedCount++;
                log.debug("用户 [{}] (ID: {}) 的登录密码已经是加密格式，跳过", user.getUsername(), user.getId());
            }

            // 检查并加密支付密码
            if (user.getPaymentPassword() == null || user.getPaymentPassword().isEmpty()) {
                // 如果没有支付密码，设置默认支付密码
                user.setPaymentPassword(passwordEncoder.encode("123456"));
                updated = true;
                paymentPasswordCount++;
                log.info("用户 [{}] (ID: {}) 设置了默认支付密码", user.getUsername(), user.getId());
            } else if (!isEncrypted(user.getPaymentPassword())) {
                String originalPaymentPassword = user.getPaymentPassword();
                String encryptedPaymentPassword = passwordEncoder.encode(originalPaymentPassword);
                user.setPaymentPassword(encryptedPaymentPassword);
                updated = true;
                paymentPasswordCount++;
                log.info("用户 [{}] (ID: {}) 的支付密码已加密", user.getUsername(), user.getId());
            }

            // 如果有更新，保存到数据库
            if (updated) {
                userMapper.updateById(user);
            }
        }

        log.info("========================================");
        log.info("密码加密完成！");
        log.info("总用户数: {}", users.size());
        log.info("登录密码已加密: {}", encryptedCount);
        log.info("登录密码已跳过: {}", skippedCount);
        log.info("支付密码已处理: {}", paymentPasswordCount);
        log.info("========================================");
    }

    /**
     * 检查密码是否已经加密
     * BCrypt加密后的密码以"$2a$"或"$2b$"或"$2y$"开头
     */
    private boolean isEncrypted(String password) {
        if (password == null || password.isEmpty()) {
            return false;
        }
        return password.startsWith("$2a$") || 
               password.startsWith("$2b$") || 
               password.startsWith("$2y$");
    }
}

